#! /usr/bin/python3

import json
import subprocess
import mraa
import sys
from collections import OrderedDict


configure_file = '/etc/board-configuration.json'


def getConfig():
    with open(configure_file, 'r') as f:
        config = json.load(f, object_pairs_hook=OrderedDict)
        return config


def saveConfig(jsonSrc):
    with open(configure_file, "w") as f:
        json.dump(jsonSrc, f, indent=4, separators=(',', ': '))


config = getConfig()


def setPinmux(index, mode):
    MODE = mode.upper()
    if 'GPIO' in MODE:
        direction = mode.split('_')[1].lstrip().rstrip().lower()
        pullMode = config['User_configuration']['IO' + str(index) + '_PULL_MODE']
        pullModeMap = {'Hiz': mraa.MODE_HIZ,
                       'Pull-up': mraa.MODE_PULLUP,
                       'Pull-down': mraa.MODE_PULLDOWN}
        gpio = mraa.Gpio(index)
        gpio.dir(mraa.DIR_OUT if direction == 'output' else mraa.DIR_IN)
        if direction == 'output':
            gpio.write(0)
        gpio.mode(pullModeMap[pullMode])
    elif 'ADC' in MODE or 'PWM' in MODE:
        mraaFuncs = {'ADC': mraa.Aio,
                     'PWM': mraa.Pwm}
        funcName = MODE.split('_')[0].lstrip().rstrip()
        pin = int(MODE.split('_')[1].lstrip().rstrip())
        mraaFuncs[funcName](pin)
    elif 'I2C_SDA' in MODE:
        mraa.I2c(0)
    elif 'SPI_SS' in MODE:
        mraa.Spi(0)
    elif 'UART_RX' in MODE:
        mraa.Uart(0)
    elif 'UART_CTS' in MODE:
        uart = mraa.Uart(0)
        uart.setFlowcontrol(False, True)


def initAruinoPins():
    for i in range(0, 20):
        io = 'IO' + str(i)
        mode = config['User_configuration'][io + '_MODE']
        if mode in config['Arduino_pinmux_map'][io]:
            setPinmux(i, mode)
        else:
            sys.stderr.write("ERROR: " + io +
                             " configuration mode [" + mode +
                             "] do not match the pinmux [" +
                             ', '.join(config['Arduino_pinmux_map'][io]) +
                             "]\n")


def initExternalSerialMode():
    command = 'grep -a -o -P "IOT2050 \w*" /proc/device-tree/model'
    boardType = subprocess.check_output(command, shell=True).lstrip().rstrip().decode('utf-8')
    initMode = config['User_configuration']['External_Serial_Init_Mode']
    currentMode = config['User_configuration']['External_Serial_Current_Mode']
    terminate = config['User_configuration']['External_Serial_Terminate']

    if initMode != currentMode:
        config['User_configuration']['External_Serial_Current_Mode'] = initMode
        saveConfig(config)

    command = ""
    if boardType == "IOT2050 Basic":
        command = "switchserialmode ttyuart -D /dev/ttyS2 -m " + initMode
    elif boardType == "IOT2050 Advanced":
        if initMode == "RS232":
            command = "switchserialmode cp210x -D cp2102n24 -m gpio -v 0"
        elif initMode == "RS485":
            command = "switchserialmode cp210x -D cp2102n24 -m RS485 -g 1"
        elif initMode == "RS422":
            command = "switchserialmode cp210x -D cp2102n24 -m gpio -v 1"

    subprocess.call(command, shell=True)
    terminateOpt = ''
    if (initMode == 'RS485') or (initMode == 'RS422'):
        terminateOpt = ' -t' if terminate == 'on' else ''
    subprocess.call("switchserialmode -m " + initMode + terminateOpt, shell=True)


def main():
    initExternalSerialMode()
    initAruinoPins()


if __name__ == '__main__':
    main()
